home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Taifun
/
Taifun 101 (1989-08-15)(Ossowski, Stefan)(DE)(PD).zip
/
Taifun 101 (1989-08-15)(Ossowski, Stefan)(DE)(PD).adf
/
Puzzle
/
Puzzle.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-04-20
|
8KB
|
424 lines
/*
* Puzzle
* ~~~~~~
* Copyright © 1989 Oo
* by o.·°
* Walter Dörwald ·°·o·.o
* O
*/
#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/rastport.h>
#include <proto/dos.h>
/* Monitor als Zufallsgenerator! */
#define RNDREG ((UBYTE *)0xDFF007)
#define rand1() ((*RNDREG)&112)
#define rand2() (((*RNDREG)&6)>>1)
/* Auch für die, die tatsächlich */
/* noch die Workbenchfarben benutzen */
#ifndef ORG
#define DUNK 0
#else
#define DUNK 2
#endif
/* Menü-returns */
#define G_NIX 0
#define G_END 1
#define G_OK 2
/* Grafik, wird automatisch ins ChipMem geladen */
extern UWORD Tile_Data[];
extern UWORD Pic_Data[];
struct TextAttr TA_NORM =
{
(UBYTE *)"topaz.font",TOPAZ_EIGHTY,FSF_BOLD,FPF_ROMFONT
};
struct Image Tile =
{
11,14,32,16,2,NULL,0x3,0x0,NULL
};
struct Image Pic =
{
5,11,148,74,2,Pic_Data,0x3,0x0,NULL
};
struct Gadget Start =
{
NULL,95,71,43,9,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,NULL,0L,NULL,2,NULL
};
struct Gadget OK =
{
&Start,20,71,43,9,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,NULL,0L,NULL,1,NULL
};
struct NewWindow NewPuzzleWin =
{
300,100,158,98,DUNK,1,MOUSEBUTTONS|CLOSEWINDOW,
RMBTRAP|ACTIVATE|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE,
NULL,NULL,(UBYTE *)" Puzzle ",NULL,NULL,0,0,0,0,WBENCHSCREEN
};
struct Window *PuzzleWin;
struct RastPort *RP;
UWORD Count;
UBYTE *Zaehl = "Züge: ·····";
#define LEN 11L
UBYTE Brett[] =
{
01,02,03,04,
05,06,07,08,
09,10,11,12,
13,14,15,00
};
UBYTE Fill[] =
{
00,01,02,03,07,11,15,14,13,12,08,04,05,06,10,09,
09,10,06,05,04,08,12,13,14,15,11,07,03,02,01,00,
00,15,01,14,02,13,03,12,07,08,11,04,10,05,09,06,
06,09,05,10,04,11,08,07,12,03,13,02,14,01,15,00,
01,00,04,05,09,08,12,13,14,15,11,10,06,07,03,02,
00,03,15,12,01,07,14,08,02,11,13,04,05,06,10,09,
00,07,14,05,12,03,10,01,08,15,06,13,04,11,02,09,
00,02,05,07,08,10,13,15,01,03,04,06,09,11,12,14
};
/* Brauch ma niat */
void MemCleanup(){}
/* Libraries */
#define INTUITION_LIB 0L
#define GRAPHICS_LIB 0L
#include "IN.lib().c"
/* Deklarationen */
UBYTE Fertig(void);
UBYTE Schieb(UBYTE);
void Set(UBYTE,UBYTE);
void SetBrett(void);
void Zug(UWORD);
UBYTE Menu(UBYTE);
void Mix(void);
void _main(void);
void _main()
{
register struct IntuiMessage *IMess;
ULONG MessClass;
UWORD Code;
register UBYTE X,
Y,
ready = FALSE;
/* Bib's auf */
OpenLib();
/* Steine mixen */
Mix();
if (PuzzleWin = OpenWindow(&NewPuzzleWin))
{
/* RastPort für schnellen Zugriff */
RP = PuzzleWin->RPort;
/* Und jetzt die ganze Grafik vorbereiten */
SetFont(RP,OpenFont(&TA_NORM));
SetAPen(RP,1);
RectFill(RP,5,11,152,94);
SetAPen(RP,3);
RectFill(RP,5,11,152,11);
RectFill(RP,5,11,7,94);
SetAPen(RP,DUNK);
SetBPen(RP,1);
/* Züge setzen und ausgeben */
Zug(Count = 0);
/* Brett zeichnen */
SetBrett();
do
{
/* Warten auf Nachricht */
WaitPort(PuzzleWin->UserPort);
while (IMess = (struct IntuiMessage *)GetMsg(PuzzleWin->UserPort))
{
/* Wichtigstes merken; Nachricht beantworten */
MessClass = IMess->Class;
Code = IMess->Code;
X = (UBYTE)IMess->MouseX;
Y = (UBYTE)IMess->MouseY;
ReplyMsg((struct Message *)IMess);
/* Verschieben */
if (MessClass == MOUSEBUTTONS)
{
switch(Code)
{
case SELECTDOWN:
/* Test ob innerhalb Grenzen */
if (X>=12 && X<=150 && Y>=14 && Y<=80)
{
X -= 12;
Y -= 14;
if ((X % 36)<26 && (Y % 18)<14)
{
X /= 36;
Y /= 18;
/* Verschieben und mitzählen */
if (Schieb((UBYTE)(X+(Y<<2))))
{
Zug(++Count);
if (Fertig())
ready = Menu(TRUE);
}
}
}
break;
case MENUDOWN:
ready = Menu(FALSE);
}
}
}
} while (MessClass != CLOSEWINDOW && ready != G_END);
/* Fenster zu */
CloseWindow(PuzzleWin);
}
/* Bib's zu */
CloseLib();
/* Das war's */
}
void Set(Pos,Num)
register UBYTE Pos,
Num;
{
/* Imagezeiger neu setzen */
/* Grafik benötigt 128 Bytes (Shift 6, da UWORD) */
Tile.ImageData = Tile_Data + (ULONG)(Num<<6);
/* Zeichnen (Offset steht in ImageStruktur) */
DrawImage(RP,&Tile,(Pos&3)*36,(Pos>>2)*18);
}
UBYTE Schieb(Pos)
register UBYTE Pos;
{
/* Pos nicht oben und oben leer ? */
if ((Pos>3) && (!Brett[Pos-4]))
Set((UBYTE)(Pos-4),Brett[Pos-4] = Brett[Pos]);
/* Pos nicht rechts und rechts leer ? */
else if (((Pos&3)<3) && (!Brett[Pos+1]))
Set((UBYTE)(Pos+1),Brett[Pos+1] = Brett[Pos]);
/* Pos nicht unten und unten leer ? */
else if ((Pos<12) && (!Brett[Pos+4]))
Set((UBYTE)(Pos+4),Brett[Pos+4] = Brett[Pos]);
/* Pos nicht links und links leer ? */
else if ((Pos&3) && (!Brett[Pos-1]))
Set((UBYTE)(Pos-1),Brett[Pos-1] = Brett[Pos]);
/* dann hald niat */
else
return(FALSE);
/* Leeres Feld neu zeichen */
Set(Pos,Brett[Pos] = 0);
return(TRUE);
}
UBYTE Fertig()
{
register UBYTE i;
/* Alle Felder testen */
for (i = 0;i<16;i++)
{
/* Liegt Stein falsch ? */
if (Brett[i] != ((i+1)&15))
return(FALSE);
}
return(TRUE);
}
void SetBrett()
{
register UBYTE i,
j,
*FillPtr;
/* Grafik wiederherstellen */
SetAPen(RP,1);
RectFill(RP,8,12,152,84);
SetAPen(RP,3);
RectFill(RP,5,11,152,11);
RectFill(RP,5,11,7,94);
SetAPen(RP,DUNK);
/* Setzmodus per Zufall */
FillPtr = Fill + rand1();
/* Leere Felder malen */
for (i = 0;i<16;i++)
{
j = FillPtr[i];
RectFill(RP,9+((j&3)*36),13+((j>>2)*18),40+((j&3)*36),28+((j>>2)*18));
Set(j,0);
Delay(3);
}
/* Steine setzen */
for (--i;i != 0xFF;i--)
{
j = FillPtr[i];
Set(j,Brett[j]);
Delay(3);
}
}
UBYTE Menu(flag)
UBYTE flag;
{
register struct IntuiMessage *IMess;
register ULONG MessClass;
register UWORD ID;
register UBYTE ret = G_NIX;
/* Grafik zeichnen */
DrawImage(RP,&Pic,0,0);
/* Gadget verwursten */
if (flag)
OK.Flags |= GADGDISABLED;
else
OK.Flags &= (!GADGDISABLED);
/* Gadgets ein */
AddGList(PuzzleWin,&OK,-1,2,NULL);
RefreshGList(&OK,PuzzleWin,NULL,2);
/* Und jetzt auf Gadgets warten */
ModifyIDCMP(PuzzleWin,GADGETUP|CLOSEWINDOW);
/* Warten auf Nachricht */
do
{
WaitPort(PuzzleWin->UserPort);
while (IMess = (struct IntuiMessage *)GetMsg(PuzzleWin->UserPort))
{
/* Wichtigstes merken; Nachricht beantworten */
MessClass = IMess->Class;
ID = ((struct Gadget *)(IMess->IAddress))->GadgetID;
ReplyMsg((struct Message *)IMess);
/* SchließGadget ? */
if (MessClass == CLOSEWINDOW)
ret = G_END;
/* Oder OK bzw. Start ? */
else
ret = G_OK;
}
} while (!ret);
/* Gadgets aus */
ModifyIDCMP(PuzzleWin,MOUSEBUTTONS|CLOSEWINDOW);
RemoveGList(PuzzleWin,&OK,2);
/* Start, dann mixen */
if ((ret == G_OK) && (ID == 2))
{
Zug(Count = 0);
Mix();
}
/* Steine wieder setzen */
if (ret != G_END)
SetBrett();
return (ret);
}
void Zug(Count)
register UWORD Count;
{
register UBYTE *i;
/* Alle Zeichen durch */
for (i = Zaehl+10;i>Zaehl+5;i--)
{
/* Ziffer setzen */
*i = '0' + (UBYTE)(Count % 10);
/* Count/10 für nächste Abfrage und testen */
Count /= 10;
}
/* Ausgeben */
Move(RP,37,92);
Text(RP,Zaehl,LEN);
}
void Mix()
{
register UWORD i;
register UBYTE Pos;
/* Leeres Feld finden */
for (Pos = 0;Pos<16;Pos++)
if (!Brett[Pos])
break;
/* Mixen, 1500× dürfte reichen (und geht auch noch schnell) */
for (i = 0;i<1500;i++)
{
switch (rand2())
{
case 0: /* Oben */
if (Pos>3)
{
Brett[Pos] = Brett[Pos -= 4];
Brett[Pos] = 0;
break;
}
case 1: /* Rechts */
if ((Pos&3) < 3)
{
Brett[Pos] = Brett[++Pos];
Brett[Pos] = 0;
break;
}
case 2: /* Unten */
if (Pos<12)
{
Brett[Pos] = Brett[Pos += 4];
Brett[Pos] = 0;
break;
}
case 3: /* Links */
if (Pos&3)
{
Brett[Pos] = Brett[--Pos];
Brett[Pos] = 0;
}
break;
}
}
}